package com.xaicode.auth.exception;

import cn.hutool.core.util.StrUtil;
import com.xaicode.auth.domain.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 全局数据库类异常处理
 * 
 * @date 2024/12/19
 */
@Slf4j
@RestControllerAdvice
public class GlobalDBExceptionHandler {

    final String REGX_DUPLICATE_KEY = "Duplicate entry '(.*)' for key '(.*)'";

    /**
     * 处理因为数据库唯一索引导致的异常
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public Result<?> duplicateKeyException(DuplicateKeyException ex, HttpServletRequest request, HttpServletResponse response) {
        // 遍历错误信息
        String errorMessage = StrUtil.blankToDefault(
                Optional.ofNullable(ex.getCause())
                        .map(Throwable::getMessage)
                        .orElse(null), ex.getMessage());
        if (StrUtil.isBlank(errorMessage)) {
            return Result.fail(ex.getMessage());
        }

        // 提取重复字段
        // eg: Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'bumen' for key 'sys_dict.uni_dict_key'
        Matcher matcher = Pattern.compile(REGX_DUPLICATE_KEY).matcher(errorMessage);
        if (matcher.find()) {
            // eg: sys_dict.uni_dict_key
            String duplicateField = matcher.group(2);
            // 对应业务名
            String businessName = parseFieldToBusinessName(duplicateField);
            // 插入值
            String duplicateFieldValue = matcher.group(1);
            if (StrUtil.isNotBlank(duplicateField)) {
                return Result.fail(String.format("%s: %s", businessName, duplicateFieldValue));
            }
        }
        return Result.fail(ex.getMessage());
    }

    // ----

    /**
     * 转换字段名为业务名，该方法与业务深度绑定
     *
     * @param field 字段名，eg: auth_sys_dict.uni_dict_key
     * @return 业务名
     */
    private String parseFieldToBusinessName(String field) {
        switch (field.toLowerCase()) {
            case "auth_sys_user.uni_username":
                return "登录名重复";
            case "auth_sys_dict.uni_dict_key":
                return "字典key重复";
            case "auth_sys_dict_detail.uni_label":
                return "字典标签重复";
            case "auth_sys_dept.uni_dept_name":
                return "同级部门名重复";
            case "auth_sys_post.uni_post_name":
                return "岗位名称重复";
            case "auth_sys_post.uni_code":
                return "岗位编码重复";
            case "auth_sys_role.uni_role_key":
                return "角色Key重复";
            case "auth_sys_role_menu.uni_role_menu":
                return "角色和菜单绑定重复";
            case "auth_sys_user_post.uni_user_post":
                return "用户和岗位绑定重复";
            case "auth_sys_user_role.uni_user_role":
                return "用户和角色绑定重复";
        }
        return "";
    }

}
